| Time | Topic |
|---|---|
| Day 1 | |
| 15:30 - 16:00 | Network Programmability & Automation |
| 16:00 - 16:30 | Ansible 101 |
| 16:30 - 17:00 | Exercise 1 |
| Day 2 | |
| 15:30 - 16:00 | Ansible 102 |
| 16:00 - 17:00 | Exercise 2 |
<rpc-reply xmlns:junos="http://xml.juniper.net/junos/13.3R5/junos">
<software-information>
<host-name>M320-TEST-re0</host-name>
<product-model>m320</product-model>
<product-name>m320</product-name>
<junos-version>13.3R5.9</junos-version>
</software-information>
<cli>
<banner>{master}</banner>
</cli>
</rpc-reply>---
parameter_defaults:
ControlPlaneDefaultRoute: "192.0.2.1"
ControlPlaneSubnetCidr: 24
DnsServers:
- "192.168.23.1"
EC2MetadataIp: "192.0.2.1"
ExternalAllocationPools:
- end: "10.0.0.250"
start: "10.0.0.4"
ExternalNetCidr: "10.0.0.1/24"
NeutronExternalNetworkBridge: ""{
"parameter_defaults": {
"ControlPlaneDefaultRoute": "192.0.2.1",
"ControlPlaneSubnetCidr": "24",
"DnsServers": [
"192.168.23.1"
],
"EC2MetadataIp": "192.0.2.1",
"ExternalAllocationPools": [
{
"end": "10.0.0.250",
"start": "10.0.0.4"
}
],
"ExternalNetCidr": "10.0.0.1/24",
"NeutronExternalNetworkBridge": ""
}
} module configuration {
namespace "http://xml.juniper.net/xnm/1.1/xnm";
prefix junos;
organization
"Juniper Networks, Inc.";
revision "2015-09-11" {
description "Initial revision";
}
typedef ipv4addr {
type string;
}
grouping juniper-config {
container backup-router {
description "IPv4 router to use while booting";
leaf address {
description "Address of router to use while booting";
type ipv4addr;
mandatory true;
}
presence "enable backup-router";
leaf-list destination {
description "Destination network reachable through the router";
type ipv4prefix;
}
}
...
https://raw.githubusercontent.com/Juniper/yang/master/14.2/configuration.yang
{% for key, value in vlanDict.iteritems() -%}
vlan {{ key }}
name {{ value }}
{% endfor %}
>>> vlanDict = {123: 'TEST-VLAN-123', 234: 'TEST-VLAN-234', 345: 'TEST-VLAN-345'}
>>> from jinja2 import Environment
>>> env = Environment(loader=FileSystemLoader('./Templates/'))
>>> template = env.get_template('ourtemplate')
>>> print template.render(vlanDict)
vlan 123
name TEST-VLAN-123
vlan 234
name TEST-VLAN-234
vlan 345
name TEST-VLAN-345[barcelona-dc]
switch01
switch02
[madrid-dc]
172.31.200.1
switch03
[barcelona-cpe]
vmx1
[madrid-cpe]
172.22.3.1
[barcelona:children]
barcelona-dc
barcelona-cpe
[all:vars]
ntp_server=10.20.30.4
[barcelona:vars]
ntp_server=192.168.0.1
[madrid:vars]
ntp_server=10.0.0.1
or
[barcelona-dc]
switch01 ntp_server=192.168.0.3
switch02
File: group_vars/barcelona-dc.yml
---
snmp:
contact: Ausias March
location: Barcelona Data Center, Passeig Colon
communities:
- community: public
type: ro
- community: private
type: rwIt's the file that contain your automation instructions
---
- name: PLAY 1 - Configure Interface Speed
hosts: barcelona-dc
connection: local
gather_facts: no
tasks:
- name: TASK1 - Get interface information
ios_command:
commands:
- show run | include interfaces
provider:
username: myusername
password: mypassword
host: "{{ inventory_hostname }}"Experiment with basic Ansible automation
All you need is here: https://github.com/chadell/ansible-cumulus-vyos
From the mgmt server:
| Time | Topic |
|---|---|
| Day 1 | |
| 15:30 - 16:00 | Network Programmability & Automation |
| 16:00 - 16:30 | Ansible 101 |
| 16:30 - 17:00 | Exercise 1 |
| Day 2 | |
| 15:30 - 16:00 | Ansible 102 |
| 16:00 - 17:00 | Exercise 2 |
Note: to find out the parameters of each module (plus some examples), you can use the ansible-doc utility: $ ansible-doc ios_config
group_vars/barcelona-dc.yml
---
snmp:
contact: Ausias March
location: Barcelona Data Center, Passeig Colon
communities:
- community: public
type: ro
- community: privat
type: rwgroup_vars/madrid-dc.yml
---
snmp:
contact: Francisco de Quevedo
location: Madrid Data Center, Paseo de la Castellana
communities:
- community: publico
type: ro
- community: privado
type: rwgroup_vars/all.yml
---
base_provider:
username: vagrant
password: vagrant
host: "{{ inventory_hostname}}"templates/snmp/ios.j2
snmp-server location {{ snmp.location }}
snmp-server contact {{ snmp.contact }}
{% for community in snmp.communities %}
snmp-server community {{ community.community }} {{ community.type | upper }}
{% endfor %}
templates/snmp/junos.j2
set snmp location {{ snmp.location }}
set snmp contact {{ snmp.contact }}
{% for community in snmp.communities %}
{% if community.type | lower == "rw" %}
set snmp community {{ community.community }} authorization read-write
{% elif community.type | lower == "ro" %}
set snmp community {{ community.community }} authorization read-only
{% endif %}
{% endfor %}
We will use the template module. It use the src parameter as the proper template to use and the dest paramter to point to the location where to store the rendered configuration (it assumes the folders already exist)
---
- name: PLAY 1 - GENERATE SNMP CONFIGURATIONS
hosts: all
connection: local
gather_facts: no
tasks:
- name: GENERATE CONFIGS FOR EACH OS
template:
src: "./snmp/{{ os }}.j2"
dest: "./configs/snmp/{{ inventory_hostname }}.cfgand run it!
$ ansible-playbook -i inventory.cfg snmp.yml[eos:vars] os=eos ```
Let's use the eos_config module to deploy the SNMP configuration from previous example
- name: PLAY 2 - ENSURE EOS SNMP CONFIGS ARE DEPLOYED
hosts: eos
connection: local
gather_facts: no
tasks:
- name: DEPLOY CONFIGS FOR EOS
eos_config:
src: "./configs/snmp/{{ inventory_hostname }}.cfg"
provider: "{{ base_provider }}"Notes: 1. This could be the second task of the previous example (we are using the output file as src) 2. We are running agains a subset of hosts (eos), and using their specific module (eos_config) 3. We are using as provider (access credentials) an object defined as a variable for all the devices, such as:
base_provider:
username: vagrant
password: vagrant
host: "{{ inventory_hostname }}Even Ansible is used often to deploy configurations it also makes possible to automate the collection of data from network devices.
In this part we will analyse two key methods for gathering data: * core facts modules * arbitrary show commands with the command module
The core facts modules return the following data as JSON (so it could be used in the playbook!):
| Core facts modules | Result |
|---|---|
| ansible_net_model | The model name returned from the device |
| ansible_net_serialnum | The serial number of the remote device |
| ansible_net_version | The operation system version running on the remote device |
| ansible_net_hostname | The configured hostname of the device |
| ansible_net_config | The current active config from the device |
| ansible_net_interfaces | A hash of all interfaces running on the system |
| ansible_net_neighbors | The list of the LLDP neighbors form the remote device |
Even by default the gather_facts provides all this information, in network devices that don't let remote python code execution (non Linux based NOS), we have to use specific modules (i.e. ios_facts:
---
- name: PLAY 1 - COLLECT FACTS FOR IOS
hosts: iosxe
connection: local
gather_facts: no
tasks:
- name: COLLECT FACTS FOR IOS
ios_facts:
provider: "{{ base_provider }}In order to view the facts that are being returned from the module you can run the playbook in verbose mode or simply yse the debug module with the var parameter while referencing a valid facts key:
# play definition omitted
tasks:
- name: COLLECT FACTS FROM IOS
ios_facts:
provider: "{{ base_provider }}"
- name: DEBUG OS VERSION
debug:
var: ansible_net version
- name: DEBUG HOSTNAME
debug:
var: ansible_net_hostnameExtend Ansible feautures to provision a network
All you need is here: https://github.com/chadell/ansible-cumulus-vyos